﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ABLoader : IAssetLoader
{
    private List<IAssetLoader> assetLoaders;
    private Dictionary<string, IAssetBundle> dicAsseetBundles;
    private Dictionary<UInt32, string> dicPrefab;
    private Dictionary<UInt32, string> dicAsset;
    private Dictionary<string, List<Action<UInt32>>> dicPrefabCallBack;     //预设加载回调字典

    private UInt32 prefabResID;
    private UInt32 assetResID;

    private AssetBundleManifest manifest;

    private List<IAssetBundle> iabs;

    public void Init()
    {
        assetLoaders = new List<IAssetLoader>();
        dicAsseetBundles = new Dictionary<string, IAssetBundle>();
        dicPrefab = new Dictionary<UInt32, string>();
        dicAsset = new Dictionary<UInt32, string>();
        prefabResID = 0;
        assetResID = 0;
        iabs = new List<IAssetBundle>();
        LoadManifest();
    }


    public IAssetBundle Create(string bundleName, Action callback)
    {
        string path = IO.GetResPath(bundleName);
        if (string.IsNullOrEmpty(path))
        {
            Debug.LogError("没有找到资源：" + bundleName);
            return null;
        }
        else
        {

            //abRequest = AssetBundle.LoadFromFileAsync(path);
            ABAssetBundle iab = new ABAssetBundle(this);
            iab.CreateRes(bundleName, callback);
            //abRequests.Add(abRequest);
            //dicIAssetBundles.Add(bundleName, iab);
            iabs.Add(iab);
            return iab;
        }
    }

    public IAssetBundle Create(string bundleName, string[] depRes, Action callback)
    {
        string path = IO.GetResPath(bundleName);
        if (string.IsNullOrEmpty(path))
        {
            Debug.LogError("没有找到资源：" + bundleName);
            return null;
        }
        else
        {

            //abRequest = AssetBundle.LoadFromFileAsync(path);
            ABAssetBundle iab = new ABAssetBundle(this);
            iab.CreateRes(bundleName, callback);
            //abRequests.Add(abRequest);
            //dicIAssetBundles.Add(bundleName, iab);
            iabs.Add(iab);
            return iab;
        }
    }



    public void UnLoad(string bundleName, bool unloadImmediately = false)
    {
        if (dicAsseetBundles.ContainsKey(bundleName))
        {

            dicAsseetBundles.Remove(bundleName);
        }
    }

    public void Load()
    {

        for (int i = 0; i < iabs.Count; i++)
        {
            if(iabs[i].IsDone())
            {
                iabs.RemoveAt(i);
            }
        }
    }

    public uint LoadPrefab(string bundleName, string assetName,  Action<uint,IAssetBundle> callback)
    {
        if (manifest == null)
        {
            LoadManifest();
        }
        ++prefabResID;
        GameObject go = null;
        if (dicAsseetBundles.ContainsKey(bundleName))
        {
            //已经存在ab资源
            IAssetBundle abRes = dicAsseetBundles[bundleName];
            //引用次数+1
            abRes.AddReferenceCount();
            //GameObject obj = abRes.LoadRes<GameObject>(assetName);
            //GameObject go1 = GameObject.Instantiate(obj);
            //GameObject g = GameObject.Find("Canvas");
            //go1.transform.SetParent(g.transform);
            //assetBundle = abRes;
            if(callback != null)
            {
                callback(prefabResID, abRes);
            }
            //UInt32 skinID = 0;
            //callback(skinID);
        }
        else
        {
            string[] depRes = manifest.GetAllDependencies(bundleName);
            if (depRes != null && depRes.Length > 0)
            {
                IAssetBundle iab = Create(bundleName, depRes, () =>
                {
                    IAssetBundle abRes = dicAsseetBundles[bundleName];
                    //GameObject obj = abRes.LoadRes<GameObject>(assetName);
                    //GameObject go1 = GameObject.Instantiate(obj);
                    //GameObject g = GameObject.Find("Canvas");
                    //go1.transform.SetParent(g.transform);
                    //UInt32 skinID = 0;
                    //callback(skinID);

                    //assetBundle = dicAsseetBundles[bundleName];
                    if (callback != null)
                    {
                        callback(prefabResID, abRes);
                    }


                });
                //assetBundle = iab;
                //if (callback != null)
                //{
                //    callback(prefabResID);
                //}
            }
            else
            {
                IAssetBundle iab = Create(bundleName, () =>
                {
                    IAssetBundle abRes = dicAsseetBundles[bundleName];
                    //GameObject obj = abRes.LoadRes<GameObject>(assetName);
                    //GameObject go1 = GameObject.Instantiate(obj);
                    //GameObject g = GameObject.Find("Canvas");
                    //go1.transform.SetParent(g.transform);
                    //UInt32 skinID = 0;
                    //callback(skinID);

                    if (callback != null)
                    {
                        callback(prefabResID, abRes);
                    }

                });
                //assetBundle = iab;
                //if (callback != null)
                //{
                //    callback(prefabResID, abRes);
                //}
            }
        }
       
        dicPrefab.Add(prefabResID, bundleName);

        return prefabResID;
    }

    public uint LoadAsset(string bundleName, Action<uint> callback)
    {
        //throw new NotImplementedException();
        if (manifest == null)
        {
            LoadManifest();
        }
        ++assetResID;
        dicAsset.Add(assetResID, bundleName);
        if (dicAsseetBundles.ContainsKey(bundleName))
        {
            //已经存在ab资源
            IAssetBundle abRes = dicAsseetBundles[bundleName];
            //引用次数+1
            abRes.AddReferenceCount();
            callback(assetResID);
        }
        else
        {
            string[] depRes = manifest.GetAllDependencies(bundleName);
            if (depRes != null && depRes.Length > 0)
            {
                IAssetBundle iab = Create(bundleName, depRes, () =>
                {
                    callback(assetResID);
                });
            }
            else
            {
                IAssetBundle iab = Create(bundleName, () => {
                    callback(assetResID);
                });
            }
        }
        
        return assetResID;
    }

    public void UnLoadPrefab(UInt32 resID)
    {
        if (dicPrefab.ContainsKey(resID))
        {
            string bundleName = dicPrefab[resID];
            dicPrefab.Remove(resID);
            if (dicAsseetBundles.ContainsKey(bundleName))
            {
                IAssetBundle iab = dicAsseetBundles[bundleName];
                iab.ReleaseRes();
            }
        }
    }

    public void UnLoadAsset(UInt32 resID)
    {
        if (dicAsset.ContainsKey(resID))
        {
            string bundleName = dicAsset[resID];
            dicAsset.Remove(resID);
            if (dicAsseetBundles.ContainsKey(bundleName))
            {
                IAssetBundle iab = dicAsseetBundles[bundleName];
                iab.ReleaseRes();
            }
        }
    }

    public Sprite GetSpriteByResIDAndName(uint resID, string spriteName)
    {
       if(dicAsset.ContainsKey(resID))
        {
            string bundleName = dicAsset[resID];
            if(dicAsseetBundles.ContainsKey(bundleName))
            {
                AssetBundle ab = dicAsseetBundles[bundleName].GetAssetBundle();
                Sprite sp = ab.LoadAsset<Sprite>(spriteName);
                if(sp == null)
                {
                    Debug.LogError(bundleName + "不存在名为：" + spriteName + "的资源");
                    return null;
                }
                else
                {
                    return sp;
                }
            }
            else
            {
                Debug.LogError("AB:" + bundleName + " 未加载");
                return null;
            }
        }
       else
        {
            Debug.LogError("resID:" + resID + ",不存在,请检查spriteName：" + spriteName + ",对应的AB资源是否已加载或者该资源是否设置AB");
            return null;
        }
    }


    //==========================================================

    /// <summary>
    /// 加载AssetBundleManifest文件
    /// </summary>
    private void LoadManifest()
    {
        string path = IO.GetAssetBundleManifsetPath();
        AssetBundle ab = AssetBundle.LoadFromFile(path);
        manifest = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }

    /// <summary>
    /// 获取以来关系
    /// </summary>
    /// <param name="bundleName"></param>
    /// <returns></returns>
    public string[] GetAllDependencies(string bundleName)
    {
        if (manifest != null)
        {
            string[] str = manifest.GetAllDependencies(bundleName);
            return str;
        }
        return null;
    }

    public void AddAssetBundle(string bundleName, IAssetBundle iab)
    {
        if (!dicAsseetBundles.ContainsKey(bundleName))
        {
            //Debug.Log("add:" + bundleName);
            dicAsseetBundles.Add(bundleName, iab);
        }
    }

    /// <summary>
    /// 检查ab资源是否已经加载
    /// </summary>
    /// <param name="bundleName"></param>
    /// <returns></returns>
    public bool CheckAssetBundle(string bundleName)
    {
        return dicAsseetBundles.ContainsKey(bundleName);
    }


    public IAssetBundle GetIAssetBundle(string bundleName)
    {
        if (dicAsseetBundles.ContainsKey(bundleName))
        {
            return dicAsseetBundles[bundleName];
        }
        return null;
    }


}
